package com.redepronik.negosysres.invfac.controller;

import static com.redepronik.negosys.utils.Utils.divide;
import static com.redepronik.negosys.utils.Utils.iva;
import static com.redepronik.negosys.utils.Utils.redondear;
import static com.redepronik.negosys.utils.Utils.timestamp;
import static com.redepronik.negosys.utils.Utils.valorSinIva;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.context.RequestContext;
import org.primefaces.event.CellEditEvent;
import org.primefaces.event.SelectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Detalleegreso;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Entrada;
import com.redepronik.negosys.invfac.entity.Local;
import com.redepronik.negosys.invfac.entity.Producto;
import com.redepronik.negosys.invfac.entity.Tipodocumento;
import com.redepronik.negosys.invfac.entityAux.CantidadFactura;
import com.redepronik.negosys.invfac.entityAux.EntradaReporte;
import com.redepronik.negosys.invfac.entityAux.FacturaReporte;
import com.redepronik.negosys.invfac.entityAux.PersonaCedulaNombre;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.invfac.service.KardexService;
import com.redepronik.negosys.invfac.service.LocalService;
import com.redepronik.negosys.invfac.service.ProductoService;
import com.redepronik.negosys.invfac.service.TipoDocumentoService;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.service.ClienteService;
import com.redepronik.negosys.rrhh.service.EmpleadoService;
import com.redepronik.negosys.rrhh.service.PersonaService;
import com.redepronik.negosysres.invfac.report.EgresoReport;

@Controller
@Scope("session")
public class EgresoAntiguoBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private ProductoService productoService;

	@Autowired
	private KardexService kardexService;

	@Autowired
	private ClienteService clienteService;

	@Autowired
	private LocalService localService;

	@Autowired
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private PersonaService personaService;

	@Autowired
	private EmpleadoService empleadoService;

	@Autowired
	private EgresoReport egresoReport;

	private List<EntradaReporte> listaEntradaReporte;
	private List<PersonaCedulaNombre> listVendedors;
	private List<Local> listaLocales;

	private Egreso egreso;
	private Persona cliente;

	private List<Producto> listProductos;
	private String nombreProducto;
	private Producto producto;

	private List<FacturaReporte> facturaReportes;
	private FacturaReporte facturaReporte;
	private CantidadFactura cantidadFacturaCalculos;
	private CantidadFactura cantidadFacturaPresentar;

	private Integer cantidad;
	private BigDecimal nuevoPrecio;

	private Integer fila;

	private List<Tipodocumento> listaTipoDocumentos;

	private boolean bn = true;

	public EgresoAntiguoBean() {
		listProductos = new ArrayList<Producto>();
		listaEntradaReporte = new ArrayList<EntradaReporte>();

		cliente = new Persona();

		producto = new Producto();
		facturaReportes = new ArrayList<FacturaReporte>();
		facturaReporte = new FacturaReporte();
		cantidadFacturaCalculos = new CantidadFactura();
		cantidadFacturaPresentar = new CantidadFactura();

	}

	public void calcularPrecioCantidad() {
		if (facturaReporte.getPrecioUnitVenta() != null) {

			facturaReporte = egresoService.calcularTotales(facturaReporte);

			facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
					.getPrecioUnitVenta()
					.add(facturaReporte.getPrecioUnitIva())));
		}
	}

	public void calcularPrecioPromocion() {

		facturaReporte.setIva(facturaReporte.isPromocion() ? "" : producto
				.getIva() ? "I" : "");

		if (facturaReporte.getCantidad() != null)
			facturaReporte = egresoService.calcularTotales(facturaReporte);

		facturaReporte.setPrecioUnitIva(facturaReporte.getIva()
				.compareToIgnoreCase("I") == 0 ? iva(facturaReporte
				.getPrecioUnitVenta()) : redondear("0.00"));

		facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
				.getPrecioUnitVenta().add(facturaReporte.getPrecioUnitIva())));
	}

	public void calcularPrecioSubTotal() {
		if (facturaReporte.getCantidad() != null) {
			facturaReporte
					.setPrecioUnitVenta(divide(facturaReporte.getSubTotal(),
							facturaReporte.getCantidad()));

			facturaReporte = egresoService.calcularTotales(facturaReporte);

			facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
					.getPrecioUnitVenta()
					.add(facturaReporte.getPrecioUnitIva())));
		}
	}

	public void calcularPrecioTotal() {
		if (facturaReporte.getCantidad() != null) {
			if (facturaReporte.getIva().compareToIgnoreCase("I") == 0)
				facturaReporte.setPrecioUnitVenta(divide(
						valorSinIva(facturaReporte.getImporte()),
						facturaReporte.getCantidad()));
			else
				facturaReporte.setPrecioUnitVenta(divide(
						facturaReporte.getImporte(),
						facturaReporte.getCantidad()));

			facturaReporte = egresoService.calcularTotales(facturaReporte);

			facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
					.getPrecioUnitVenta()
					.add(facturaReporte.getPrecioUnitIva())));

		}
	}

	public void calcularPrecioUnit() {
		if (facturaReporte.getIva().compareToIgnoreCase("I") == 0)
			facturaReporte.setPrecioUnitVenta(valorSinIva(facturaReporte
					.getPrecioUnitTotal()));
		else
			facturaReporte.setPrecioUnitVenta(facturaReporte
					.getPrecioUnitTotal());

		if (facturaReporte.getCantidad() != null)
			facturaReporte = egresoService.calcularTotales(facturaReporte);

	}

	public void cambiarCantidad() {
		FacturaReporte f = facturaReportes.get(fila);

		if (cantidad <= 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "INGRESE UNA CANTIDAD MAYOR QUE CERO"));
		else if (cantidad != f.getCantidad())
			facturaReportes.set(fila, egresoService.recalcular(fila, f,
					egreso.getDetalleegresos(), cantidadFacturaCalculos,
					cantidad, null, true));

		cantidad = null;
		fila = null;
	}

	public void cambiarPrecio() {
		FacturaReporte f = facturaReportes.get(fila);

		BigDecimal precio = productoService.obtenerPorProductoId(
				f.getProductoId()).getPrecio();
		if (nuevoPrecio.compareTo(precio) < 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "EL PRECIO NO DEBE SER MENOR AL PRECIO DE COSTO: "
							+ precio));
		else if (nuevoPrecio != f.getPrecioUnitVenta())
			facturaReportes.set(fila, egresoService.recalcular(fila, f,
					egreso.getDetalleegresos(), cantidadFacturaCalculos, null,
					nuevoPrecio, true));

		nuevoPrecio = null;
		fila = null;
	}

	public void cancelar() {
		facturaReporte = new FacturaReporte();
	}

	public void cancelarTodo() {
		bn = true;
		xxx();
		cliente = new Persona();
		listaEntradaReporte = new ArrayList<EntradaReporte>();
		facturaReportes = new ArrayList<FacturaReporte>();
		cantidadFacturaCalculos = new CantidadFactura();
	}

	public void cargarCliente(SelectEvent event) {
		cliente = clienteService.obtenerPorPersonaId(cliente.getPersonaid());
		egreso.setCliente(cliente.getCliente());
	}

	public void cargarProducto(SelectEvent event) {
		producto = productoService.obtenerPorProductoId(producto
				.getProductoid());
		facturaReporte.setProductoId(producto.getProductoid());
		facturaReporte.setPrecioId(producto.getTipoPrecioProductos().get(0)
				.getTipoprecioproductoid());

		obtenerPrecio();
	}

	public boolean comprobar() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;
		if (egreso.getCliente() == null) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "DEBE INGRESAR UN CLIENTE"));
		}
		if (egreso.getDetalleegresos().isEmpty()) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "DEBE INGRESAR DETALLES"));
		}
		// if (egreso.getVendedor().getVendedorid() == 0) {
		// bn = false;
		// presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
		// "ERROR", "DEBE INGRESAR UN VENDEDOR"));
		// }

		if (bn)
			context.addCallbackParam("error", true);
		else
			context.addCallbackParam("error", false);

		return bn;
	}

	public void comprobarClienteLocal() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;
		if (egreso.getCliente() == null) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "DEBE ESCOJER PRIMERO UN CLIENTE"));
		}
		if (egreso.getLocal().getLocalid() == null) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "DEBE ESCOJER UN LOCAL"));
		}
		if (egreso.getLocal().getLocalid() != null) {
			Local local = localService.obtenerPorLocalId(egreso.getLocal()
					.getLocalid());
			if (local.getBodegalocals() == null
					&& local.getBodegalocals().isEmpty()) {
				bn = false;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"ERROR",
						"EL LOCAL QUE ESCOJIO NO TIENE BODEGAS ASOCIADAS"));
			}
		}

		if (bn)
			context.addCallbackParam("error1", true);
		else
			context.addCallbackParam("error1", false);
	}

	public void comprobarPrecioCosto() {
		BigDecimal precio = productoService.obtenerPorProductoId(
				facturaReporte.getProductoId()).getPrecio();
		if (facturaReporte.getPrecioUnitVenta().compareTo(precio) < 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "EL PRECIO NO DEBE SER MENOR AL PRECIO DE COSTO: "
							+ precio));
		else {
			if (facturaReporte.getCantidad() != null)
				facturaReporte = egresoService.calcularTotales(facturaReporte);

			if (facturaReporte.getIva().compareToIgnoreCase("I") == 0)
				facturaReporte.setPrecioUnitIva(iva(facturaReporte
						.getPrecioUnitVenta()));
			else
				facturaReporte.setPrecioUnitIva(redondear("0.00"));

			facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
					.getPrecioUnitVenta()
					.add(facturaReporte.getPrecioUnitIva())));
		}
	}

	public void eliminarDetalle(ActionEvent actionEvent) {
		int posicion = egresoService.posicion(facturaReporte,
				egreso.getDetalleegresos(), true);
		if (posicion >= 0) {
			Detalleegreso de = egreso.getDetalleegresos().get(posicion);
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
					"ELIMINÓ DETALLE", "Elimino: " + de.getProducto().getEan()));
			egreso.removeDetalleegreso(de);
			cantidadFacturaCalculos = egresoService.calcularCantidadFactura(
					cantidadFacturaCalculos, facturaReporte, "subtract");
			facturaReportes.remove(facturaReporte);
			cancelar();
		}
	}

	public Integer getCantidad() {
		return cantidad;
	}

	public CantidadFactura getCantidadFacturaCalculos() {
		return cantidadFacturaCalculos;
	}

	public CantidadFactura getCantidadFacturaPresentar() {
		return egresoService.redondearCantidadFactura(cantidadFacturaPresentar,
				cantidadFacturaCalculos);
	}

	public Persona getCliente() {
		return cliente;
	}

	public Egreso getEgreso() {
		return egreso;
	}

	public FacturaReporte getFacturaReporte() {
		return facturaReporte;
	}

	public List<FacturaReporte> getFacturaReportes() {
		return facturaReportes;
	}

	public List<EntradaReporte> getListaEntradaReporte() {
		return listaEntradaReporte;
	}

	public List<Local> getListaLocales() {
		return listaLocales;
	}

	public List<Tipodocumento> getListaTipoDocumentos() {
		return listaTipoDocumentos;
	}

	public List<Producto> getListProductos() {
		return listProductos;
	}

	public List<PersonaCedulaNombre> getListVendedors() {
		return listVendedors;
	}

	public String getNombreProducto() {
		return nombreProducto;
	}

	public BigDecimal getNuevoPrecio() {
		return nuevoPrecio;
	}

	public Producto getProducto() {
		return producto;
	}

	@PostConstruct
	public void init() {
		setListaLocales(localService.obtenerPorCajero(SecurityContextHolder
				.getContext().getAuthentication().getName()));
		// listVendedors = vendedorService.obtener();
		listaTipoDocumentos = tipoDocumentoService.obtener(true);
		xxx();
	}

	public void insertarDetalle(ActionEvent actionEvent) {
		producto = productoService.obtenerPorProductoId(producto
				.getProductoid());

		if (facturaReporte.getCantidad() > 0) {
			Detalleegreso detalleEgreso = new Detalleegreso();

			detalleEgreso.setProducto(producto);

			facturaReporte = egresoService.asignar(detalleEgreso,
					facturaReporte, 0);

			detalleEgreso.setCantidad(facturaReporte.getCantidad());
			detalleEgreso.setPreciocosto(producto.getPrecio());
			detalleEgreso.setPrecioventa(facturaReporte.getPrecioUnitVenta());
			detalleEgreso.setIva(producto.getIva());
			detalleEgreso.setPromocion(facturaReporte.isPromocion());
			detalleEgreso.setEliminar(facturaReporte.isEliminar());

			cantidadFacturaCalculos = egresoService.calcularCantidadFactura(
					cantidadFacturaCalculos, facturaReporte, "add");

			facturaReportes.add(facturaReporte);
			egreso.addDetalleegreso(detalleEgreso);

			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
					"INSERTÓ DETALLE", "INSERTO: " + producto.getEan()));
			cancelar();
			producto = new Producto();
			listProductos = new ArrayList<Producto>();
		} else
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "INGRESE UNA CANTIDAD MAYOR QUE CERO"));
	}

	public void insertarOrActualizar(ActionEvent actionEvent) {
		if (comprobar()) {
			egreso.setPagado(false);
			egreso.setDevolucion(true);
			egreso.setCajeroid(empleadoService
					.obtenerPorCedula(
							SecurityContextHolder.getContext()
									.getAuthentication().getName())
					.getEmpleado().getEmpleadocargos().get(0));
			egreso.setFechainicio(timestamp());
			egreso.setClienteFactura(egreso.getCliente());

			egresoService.insertar(egreso, null);
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
					"INSERTÓ", "Egreso: " + egreso.getCodigodocumento()));
		}

	}

	public boolean isBn() {
		return bn;
	}

	public void obtenerBodega() {
		if (egreso.getLocal().getLocalid() != 0)
			egreso.setLocal(localService.obtenerPorLocalId(egreso.getLocal()
					.getLocalid()));
	}

	public void obtenerFila(CellEditEvent event) {
		fila = event.getRowIndex();
	}

	public void obtenerPrecio() {
		// corregir lo de bodega ojo
		facturaReporte.setPrecioUnitVenta(productoService.calcularPrecio(
				producto, 1, facturaReporte.getPrecioId()));

		facturaReporte.setIva(facturaReporte.isPromocion() ? "" : producto
				.getIva() ? "I" : "");

		if (facturaReporte.getCantidad() != null)
			facturaReporte = egresoService.calcularTotales(facturaReporte);

		facturaReporte.setPrecioUnitIva(facturaReporte.getIva()
				.compareToIgnoreCase("I") == 0 ? iva(facturaReporte
				.getPrecioUnitVenta()) : redondear("0.00"));

		facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
				.getPrecioUnitVenta().add(facturaReporte.getPrecioUnitIva())));
	}

	public void obtenerProductos() {
		if (!nombreProducto.equals(null))
			listProductos = productoService.obtenerPorLocal(nombreProducto,
					egreso.getLocal().getLocalid());
	}

	private void presentaMensaje(FacesMessage message) {
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	public void setBn(boolean bn) {
		this.bn = bn;
	}

	public void setCantidad(Integer cantidad) {
		this.cantidad = cantidad;
	}

	public void setCantidadFacturaCalculos(
			CantidadFactura cantidadFacturaCalculos) {
		this.cantidadFacturaCalculos = cantidadFacturaCalculos;
	}

	public void setCantidadFacturaPresentar(
			CantidadFactura cantidadFacturaPresentar) {
		this.cantidadFacturaPresentar = cantidadFacturaPresentar;
	}

	public void setCliente(Persona cliente) {
		this.cliente = cliente;
	}

	public void setEgreso(Egreso egreso) {
		this.egreso = egreso;
	}

	public void setFacturaReporte(FacturaReporte facturaReporte) {
		this.facturaReporte = facturaReporte;
	}

	public void setFacturaReportes(List<FacturaReporte> facturaReportes) {
		this.facturaReportes = facturaReportes;
	}

	public void setListaEntradaReporte(List<EntradaReporte> listaEntradaReporte) {
		this.listaEntradaReporte = listaEntradaReporte;
	}

	public void setListaLocales(List<Local> listaLocales) {
		this.listaLocales = listaLocales;
	}

	public void setListaTipoDocumentos(List<Tipodocumento> listaTipoDocumentos) {
		this.listaTipoDocumentos = listaTipoDocumentos;
	}

	public void setListProductos(List<Producto> listProductos) {
		this.listProductos = listProductos;
	}

	public void setListVendedors(List<PersonaCedulaNombre> listVendedors) {
		this.listVendedors = listVendedors;
	}

	public void setNombreProducto(String nombreProducto) {
		this.nombreProducto = nombreProducto;
	}

	public void setNuevoPrecio(BigDecimal nuevoPrecio) {
		this.nuevoPrecio = nuevoPrecio;
	}

	public void setProducto(Producto producto) {
		this.producto = producto;
	}

	private void xxx() {
		egreso = new Egreso();
		egreso.setLocal(new Local());
		// egreso.setVendedor(new Vendedor());
		egreso.setEntradas(new ArrayList<Entrada>());
		egreso.setDetalleegresos(new ArrayList<Detalleegreso>());
		egreso.setTipodocumento(new Tipodocumento());
	}

}